using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace SiKuma.ScreenSystemLibrary
{
    public class ScreenSystem : DrawableGameComponent
    {
        private List<GameScreen> screens = new List<GameScreen>();
        private List<GameScreen> screensToUpdate = new List<GameScreen>();
        private bool isInitialized;

        public SpriteBatch SpriteBatch
        {
            get;
            private set;
        }

        public ContentManager Content
        {
            get
            {
                return base.Game.Content;
            }
        }

        public Viewport Viewport
        {
            get
            {
                return base.GraphicsDevice.Viewport;
            }
        }

        public ScreenSystem(Game game)
            : base(game)
        {
            base.Initialize();
            this.isInitialized = true;
        }

        protected override void LoadContent()
        {
            this.SpriteBatch = new SpriteBatch(base.GraphicsDevice);
            foreach (GameScreen current in this.screens)
            {
                if (!current.IsContentLoaded)
                {
                    current.LoadContent();
                }
            }
        }

        protected override void UnloadContent()
        {
            foreach (GameScreen current in this.screens)
            {
                if (!current.IsContentUnloaded)
                {
                    current.UnloadContent();
                }
            }
        }

        public override void Update(GameTime gameTime)
        {
            this.screensToUpdate.Clear();
            if (this.screens.Count == 0)
            {
                base.Game.Exit();
            }
            foreach (GameScreen current in this.screens)
            {
                this.screensToUpdate.Add(current);
            }
            if (!base.Game.IsActive)
            {
                return;
            }
            while (this.screensToUpdate.Count > 0)
            {
                GameScreen gameScreen = this.screensToUpdate[this.screensToUpdate.Count - 1];
                this.screensToUpdate.RemoveAt(this.screensToUpdate.Count - 1);
                if (gameScreen.State != ScreenState.Frozen && gameScreen.State != ScreenState.Inactive)
                {
                    gameScreen.Update(gameTime);
                }
                if (gameScreen.IsActive && gameScreen.AcceptsInput)
                {
                    gameScreen.HandleInput();
                }
            }
        }

        public override void Draw(GameTime gameTime)
        {
            if (!base.Game.IsActive)
            {
                return;
            }
            foreach (GameScreen current in this.screens)
            {
                if (current.State != ScreenState.Hidden)
                {
                    current.Draw(gameTime);
                }
            }
        }

        public void AddScreen(GameScreen screen)
        {
            screen.ScreenSystem = this;
            if (this.isInitialized)
            {
                screen.Initialize();
                screen.InitializeScreen();
                screen.LoadContent();
            }
            this.screens.Add(screen);
        }

        public void RemoveScreen(GameScreen screen)
        {
            if (this.isInitialized && !screen.IsContentUnloaded)
            {
                screen.UnloadContent();
            }
            this.screens.Remove(screen);
        }
    }
}
